package com.canyou.activiti.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.canyou.activiti.entity.ActHighLineVO;
import com.canyou.activiti.entity.ActHistoryVO;
import com.canyou.activiti.entity.FormDataVO;
import com.canyou.activiti.service.ActHistoryService;
import com.canyou.activiti.service.ActTaskService;
import com.canyou.utils.Oauth2Utils;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author canyou
 * @since 2021-03-02
 */
@Service
public class ActHistoryServiceImpl implements ActHistoryService {

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ActTaskService actTaskService;

    @Override
    public IPage<ActHistoryVO> getPageList(IPage<ActHistoryVO> page) {
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc()
                .taskAssignee(Oauth2Utils.getUserName());
        // 查询records
        List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.listPage((int) ((page.getCurrent() - 1) * page.getSize()), (int) page.getSize());
        List<ActHistoryVO> list = new ArrayList<>();
        if (historicTaskInstanceList != null && !historicTaskInstanceList.isEmpty()) {
            list = historicTaskInstanceList.parallelStream()
                    .map(tk -> {
                        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                                .processInstanceId(tk.getProcessInstanceId())
                                .singleResult();
                        return new ActHistoryVO()
                                .setId(tk.getId())
                                .setName(tk.getName())
                                .setCreateTime(tk.getCreateTime())
                                .setDescription(tk.getDescription())
                                .setProcessDefinitionKey(historicProcessInstance.getProcessDefinitionKey())
                                .setProcessInstanceName(historicProcessInstance.getName())
                                .setStartTime(tk.getStartTime())
                                .setClaimTime(tk.getClaimTime())
                                .setEndTime(tk.getEndTime())
                                .setAssignee(tk.getAssignee());
                    })
                    .collect(Collectors.toList());
        }
        page.setRecords(list);
        // 查询总条数
        page.setTotal(historicTaskInstanceQuery.count());
        return page;
    }

    @Override
    public ActHighLineVO getHighLine(String instanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(instanceId)
                .singleResult();
        // 获取bpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
        // 因为我们这里只定义了一个Process 所以获取集合中的第一个即可
        Process process = bpmnModel.getProcesses().get(0);
        // 获取所有的FlowElement信息
        Collection<FlowElement> flowElements = process.getFlowElements();

        Map<String, String> map = new HashMap<>(10);
        for (FlowElement flowElement : flowElements) {
            //判断是否是连线
            if (flowElement instanceof SequenceFlow) {
                SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
                String ref = sequenceFlow.getSourceRef();
                String targetRef = sequenceFlow.getTargetRef();
                map.put(ref + targetRef, sequenceFlow.getId());
            }
        }

        // 获取流程实例 历史节点(全部)
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .list();
        // 各个历史节点 两两组合 key
        Set<String> keyList = new HashSet<>();
        for (HistoricActivityInstance i : list) {
            for (HistoricActivityInstance j : list) {
                if (i != j) {
                    keyList.add(i.getActivityId() + j.getActivityId());
                }
            }
        }
        // 高亮连线ID
        Set<String> highLine = new HashSet<>();
        keyList.forEach(s -> highLine.add(map.get(s)));


        // 获取流程实例 历史节点（已完成）
        List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .finished()
                .list();
        // 高亮节点ID
        Set<String> highPoint = new HashSet<>();
        listFinished.forEach(s -> highPoint.add(s.getActivityId()));

        // 获取流程实例 历史节点（待办节点）
        List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .unfinished()
                .list();

        // 需要移除的高亮连线
        Set<String> set = new HashSet<>();
        // 待办高亮节点
        Set<String> waitingToDo = new HashSet<>();
        listUnFinished.forEach(s -> {
            waitingToDo.add(s.getActivityId());

            for (FlowElement flowElement : flowElements) {
                // 判断是否是 用户节点
                if (flowElement instanceof UserTask) {
                    UserTask userTask = (UserTask) flowElement;

                    if (userTask.getId().equals(s.getActivityId())) {
                        List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
                        // 因为 高亮连线查询的是所有节点  两两组合 把待办 之后  往外发出的连线 也包含进去了  所以要把高亮待办节点 之后 即出的连线去掉
                        if (outgoingFlows != null && outgoingFlows.size() > 0) {
                            outgoingFlows.forEach(a -> {
                                if (a.getSourceRef().equals(s.getActivityId())) {
                                    set.add(a.getId());
                                }
                            });
                        }
                    }
                }
            }
        });

        highLine.removeAll(set);
        // 存放 高亮 我的办理节点
        Set<String> iDo = new HashSet<>();
        // 当前用户已完成的任务
        List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
//                    .taskAssignee(SecurityUtils.getUsername())
                .finished()
                .processInstanceId(instanceId).list();

        taskInstanceList.forEach(a -> iDo.add(a.getTaskDefinitionKey()));

        return new ActHighLineVO()
                .setHighPoint(highPoint)
                .setHighLine(highLine)
                .setWaitingToDo(waitingToDo)
                .setIDo(iDo);
    }

    @Override
    public List<FormDataVO> getHistoryFormData(String instanceId) {
        // 获取流程实例 历史节点（已完成）
        List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .finished()
                .list();
        if (listFinished == null || listFinished.isEmpty()) {
            return null;
        }
        // 找到所有的用户任务然后查找表单和用户输入值
        return listFinished.stream()
                .filter(finishedInst -> "userTask".equalsIgnoreCase(finishedInst.getActivityType()))
                .map(finishedInst -> actTaskService.getFormData(finishedInst.getTaskId())
                        .setAssignee(finishedInst.getAssignee()))
                .collect(Collectors.toList());
    }

}
